package mlpEnsemble;

import genetic_algorithm.Chromosome;
import genetic_algorithm.Crossover;
import genetic_algorithm.GeneticAlgorithm;
import genetic_algorithm.Mutation;
import genetic_algorithm.Population;
import genetic_algorithm.Selection;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JOptionPane;

import utils.GAretVal;
import digitRecognitionProblem.DigitRecognitionSelector;

/**
 * Runs a genetic algorithm to find the optimal bags of neural networks.
 * ATTENTION: before running, the activation function of mlp.Neuron.java must be set to tanh
 * and mlp.NEGATIVE should be -1
 */
public class MlpEnsemble {
	
	private static int MAX_GENS = 120; // maximal number of generations to run
	private static final int CROSSOVER_MODE = MlpEnsembleCrossover.SINGLE_POINT; // the mode of DigitRecognitionCrossover;
	private static int POP_SIZE = 150; //400; // 100 // 50; // number of chromosomes in the population
	private static final double CROSSOVER_RATE = 0.95; // chance to perform crossover
	private static final double MUTATION_RATE = 0.2; // chance to perform mutation
	private static final String TEST_FILE1 = "validate1_reduce.csv";
	private static boolean REMOVE_PARENTS = false; // if chromosomes can be selected only once
	private static final int CHROMOSOME_SIZE = 25;
	private static final int NUM_MLPS = 50; // number of neural networks for each digit

	public static void main(String[] args) {
		
		MAX_GENS = 
		        Integer.parseInt(JOptionPane.showInputDialog ( "Insert number of generation?" )); 
		POP_SIZE = 
		        Integer.parseInt(JOptionPane.showInputDialog ( "Insert population size?" )); 

		// allocate objects to implement each phase of the genetic algorithm
		MlpEnsembleFitness.initTestData(TEST_FILE1);		
		MlpEnsembleFitness fitnessFunction = new MlpEnsembleFitness();
		
		Crossover crossover = new MlpEnsembleCrossover(CROSSOVER_MODE);
		Selection selector = new DigitRecognitionSelector(REMOVE_PARENTS);
		Mutation mutation = new MlpEnsembleMutation(NUM_MLPS);
		
		// create initial population
		List<Chromosome> chromList = new LinkedList<Chromosome>();
		
		for (int i = 0; i < POP_SIZE; ++i) {
			chromList.add(new MlpEnsembleChromosome(NUM_MLPS,CHROMOSOME_SIZE));				
		}
		Population population = new Population(chromList, fitnessFunction);
		
		
		MlpEnsembleFitness.initTestData(TEST_FILE1);		
		// initialize the genetic algorithm
		GeneticAlgorithm GA = new GeneticAlgorithm(fitnessFunction, crossover,
				selector, mutation, CROSSOVER_RATE, MUTATION_RATE);

		// find optimal solution
		GAretVal result = GA.execute(population, MAX_GENS, true, 6);

		// generate csv for execution data
		result.createsCsvFiles("mlp_ensemble");
		
		FileOutputStream writeFile;
		try {
			writeFile = new FileOutputStream("BEST_CHROM.txt");
			ObjectOutputStream fileStream1 = new ObjectOutputStream(writeFile);
			fileStream1.writeObject(result.getOptSolution());
			fileStream1.close();
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}	
}
